package com.yilin.platform.base_core.tools.pab.entity;

import com.yilin.platform.base_core.commons.utils.DateTimeUtil;
import com.yilin.platform.base_core.tools.pab.base.SplitRange;

import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DataXmlHeader implements Serializable {

    @SplitRange(begin = 0, len = 6)
    private String xmlCategory; //报文类别和目标系统编号
    @SplitRange(begin = 6, len = 2)
    private String encoded; //报文编码
    @SplitRange(begin = 8, len = 2)
    private String reqProtocol; //通讯协议
    @SplitRange(begin = 10, len = 20)
    private String merchantCode; //企业银企直连标准代码
    @SplitRange(begin = 30, len = 10)
    private Integer bodyLength; //接收报文长度
    @SplitRange(begin = 40, len = 6)
    private String tradeCode; //交易码
    @SplitRange(begin = 46, len = 5)
    private String optCode; //操做员代码
    @SplitRange(begin = 51, len = 2)
    private Integer serviceType; //服务类型
    @SplitRange(begin = 53, len = 8)
    private Integer reqDate; //交易日期
    @SplitRange(begin = 61, len = 6)
    private Integer reqTime; //交易时间
    @SplitRange(begin = 67, len = 20)
    private String resFlowNo; //请求方系统流水号
    @SplitRange(begin = 87, len = 6)
    private String resCode; //返回码
    @SplitRange(begin = 93, len = 100)
    private String resMsg; //返回描述
    @SplitRange(begin = 193, len = 1)
    private String isReqFollow; //后续包标志
    @SplitRange(begin = 194, len = 3)
    private String reqFollowCount; //请求次数
    @SplitRange(begin = 197, len = 1)
    private String signature; //签名标识
    @SplitRange(begin = 198, len = 1)
    private String signFormat; //签名数据包格式
    @SplitRange(begin = 199, len = 12)
    private String signAlgorithm; //签名算法
    @SplitRange(begin = 211, len = 10)
    private Integer signDataLength; //签名数据长度
    @SplitRange(begin = 221, len = 1)
    private Integer annexCount; //附件数目

    private Date tradeDate; //親求日期時間

    @Override
    public String toString() {
        if (tradeDate != null) setSplitDateTime();
        return fillSpace(xmlCategory, 6) +//6位
                fillSpace(encoded, 2) +//编码格式：01：GBK 02：UTF-8 (建议使用GBK编码)
                fillSpace(reqProtocol, 2) +//请求协议： 02：http
                fillSpace(merchantCode, 20) +//商户代码： 20位
                fillZero(bodyLength, 10) +//报文体程度10位
                fillSpace(tradeCode, 6) +//接口交易码6位
                fillSpace(optCode, 5) +//操作员代码5位
                fillZero(serviceType, 2) +//01-请求 02-应答
                fillZero(reqDate, 8) +//请求日期
                fillZero(reqTime, 6) +//请求时间
                fillSpace(resFlowNo, 20) +//流水号 20位-----必填20位
                fillSpace(resCode, 6) +//返回码
                fillSpace(resMsg, 100) +// 返回码请求不输
                fillSpace(isReqFollow, 1) +//0-结束包
                fillSpace(reqFollowCount, 3) + // 如果有后续包请求 目前仅支持000
                fillSpace(signature, 1) +//0-不签名
                fillSpace(signFormat, 1) +//1-填1，企业不管，由银行客户端完成
                fillSpace(signAlgorithm, 12) +//签名算法: 长度12
                fillZero(signDataLength, 10) +//签名报文数据长度：企业不需要签名
                fillZero(annexCount, 1);//附件数目
    }


    //报文头补0: 左补‘0’
    private String fillZero(Integer value, int length) {
        if (value == null) value = 0;
        return fill(String.valueOf(value), length, true);
    }

    //报文头补空格: 右补‘ ’
    private String fillSpace(String str, int length) {
        if (str == null) str = "";
        return fill(str, length, false);
    }

    private String fill(String str, int length, boolean num) {
        if (str.length() < length) {
            int diff = length - str.length();
            StringBuilder strBuilder = new StringBuilder(str);
            for (int i = 0; i < diff; i++) {
                if (num) strBuilder.insert(0, "0");
                else strBuilder.append(" ");
            }
            return strBuilder.toString();
        }
        return str.substring(0, length);
    }

    public Date toTradeDate() {
        if (reqDate == null || reqTime == null) return null;
        String dateStr = reqDate + String.valueOf(reqTime);
        return DateTimeUtil.stringToDate(dateStr, "yyyyMMddHHmmss");
    }

    private void setSplitDateTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-HHmmss");
        String[] split = sdf.format(tradeDate).split("-");
        reqDate = Integer.parseInt(split[0]);
        reqTime = Integer.parseInt(split[1]);
    }

    public Date getTradeDate() {
        return tradeDate;
    }

    public void setTradeDate(Date tradeDate) {
        this.tradeDate = tradeDate;
    }

    public String getResFlowNo() {
        return resFlowNo;
    }

    public void setResFlowNo(String resFlowNo) {
        this.resFlowNo = resFlowNo;
    }

    public String getXmlCategory() {
        return xmlCategory;
    }

    public void setXmlCategory(String xmlCategory) {
        this.xmlCategory = xmlCategory;
    }

    public String getEncoded() {
        return encoded;
    }

    public void setEncoded(String encoded) {
        this.encoded = encoded;
    }

    public String getReqProtocol() {
        return reqProtocol;
    }

    public void setReqProtocol(String reqProtocol) {
        this.reqProtocol = reqProtocol;
    }

    public String getMerchantCode() {
        return merchantCode;
    }

    public void setMerchantCode(String merchantCode) {
        this.merchantCode = merchantCode;
    }

    public Integer getBodyLength() {
        return bodyLength;
    }

    public void setBodyLength(Integer bodyLength) {
        this.bodyLength = bodyLength;
    }

    public String getTradeCode() {
        return tradeCode;
    }

    public void setTradeCode(String tradeCode) {
        this.tradeCode = tradeCode;
    }

    public String getOptCode() {
        return optCode;
    }

    public void setOptCode(String optCode) {
        this.optCode = optCode;
    }

    public Integer getServiceType() {
        return serviceType;
    }

    public void setServiceType(Integer serviceType) {
        this.serviceType = serviceType;
    }

    public Integer getReqDate() {
        return reqDate;
    }

    public void setReqDate(Integer reqDate) {
        this.reqDate = reqDate;
    }

    public Integer getReqTime() {
        return reqTime;
    }

    public void setReqTime(Integer reqTime) {
        this.reqTime = reqTime;
    }

    public String getResCode() {
        return resCode;
    }

    public void setResCode(String resCode) {
        this.resCode = resCode;
    }

    public String getResMsg() {
        return resMsg;
    }

    public void setResMsg(String resMsg) {
        this.resMsg = resMsg;
    }

    public String getIsReqFollow() {
        return isReqFollow;
    }

    public void setIsReqFollow(String isReqFollow) {
        this.isReqFollow = isReqFollow;
    }

    public String getReqFollowCount() {
        return reqFollowCount;
    }

    public void setReqFollowCount(String reqFollowCount) {
        this.reqFollowCount = reqFollowCount;
    }

    public String getSignature() {
        return signature;
    }

    public void setSignature(String signature) {
        this.signature = signature;
    }

    public String getSignFormat() {
        return signFormat;
    }

    public void setSignFormat(String signFormat) {
        this.signFormat = signFormat;
    }

    public String getSignAlgorithm() {
        return signAlgorithm;
    }

    public void setSignAlgorithm(String signAlgorithm) {
        this.signAlgorithm = signAlgorithm;
    }

    public Integer getSignDataLength() {
        return signDataLength;
    }

    public void setSignDataLength(Integer signDataLength) {
        this.signDataLength = signDataLength;
    }

    public Integer getAnnexCount() {
        return annexCount;
    }

    public void setAnnexCount(Integer annexCount) {
        this.annexCount = annexCount;
    }
}
